# shellcheck shell=bash

# Write a stylized header, but fall back to plain text
# Args:
#   $@: Message to print
function cki_say {
    # shellcheck disable=SC2312  # runs in set -e
    echo "$@" | toilet -f smmono12 -w 300 | lolcat -f || echo "$@"
}

# Write a bold green message (that looks like gitlab-runner's messages).
# Args:
#   $*: Message to print in green
function cki_echo_green {
    echo -e "\e[1;32m$*\e[0m"
}

# Write a bold red message (that looks like gitlab-runner's messages).
# Args:
#   $*: Message to print in red
function cki_echo_red {
    echo -e "\e[1;31m$*\e[0m"
}

# Write a bold yellow message (that looks like gitlab-runner's messages).
# Args:
#   $*: Message to print in red
function cki_echo_yellow {
    echo -e "\e[1;33m$*\e[0m"
}

# Parse a deployment-all-style bucket specification.
# Args:
#   $1: NAME of the env variable containing the bucket spec, eg.
#       "http://localhost:9000|cki_temporary|super_secret|software|subpath/"
# Exported variables:
#   AWS_ENDPOINT
#   AWS_ACCESS_KEY_ID
#   AWS_SECRET_ACCESS_KEY
#   AWS_BUCKET
#   AWS_BUCKET_PATH
function cki_parse_bucket_spec {
    IFS='|' read -r AWS_ENDPOINT AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_BUCKET AWS_BUCKET_PATH <<< "${!1}"
    export AWS_ENDPOINT AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_BUCKET AWS_BUCKET_PATH
}

# Call openssl enc with reasonable defaults
# Args:
#   $1: NAME of the env variable containing the password
#   $@: additional arguments for openssl enc
# Examples:
# - encrypt and save as base64: echo "secret" | cki_openssl_enc PASSWORD -e -a
# - decrypt again: echo "$ENCRYPTED_BASE64" | cki_openssl_enc PASSWORD -d -a
function cki_openssl_enc() {
    # OpenSSL parameters extracted from https://askubuntu.com/a/1126882
    openssl enc \
        -aes-256-cbc \
        -md sha512 \
        -pbkdf2 \
        -iter 100000 \
        -salt \
        -pass "env:$1" \
        "${@:2}"
}

# Check if the passed variable has a truthy value or not.
# Args: Variable
# Returns: 0 if the variable is truthy, 1 otherwise
function cki_is_true {
    if [[ "${1}" = [Tt]rue ]] ; then
        return 0
    else
        return 1
    fi
}

# Canonicalize a git repository URL.
#
# Result: https://gitlab.com/cki-project/cki-tools.git/
function cki_git_clean_url() {
    local repo_url=$1
    repo_url=${repo_url#*//}
    repo_url=${repo_url%/}
    repo_url=${repo_url%.git}
    echo "https://${repo_url}.git/"
}

# Clone a gitlab.com/cki-project git repository and keep it updated.
#
# When called repeatedly, it will pull the repo once a day. The environment
# variable <package_name>_pip_url can be used to modify the repo URL, e.g. for
# testing.
#
# Usage: cki_update_repo https://gitlab.com/cki-project/inventory
function cki_update_repo {
    local last_fetch threshold check_interval
    local repo_url repo_name pip_url resolved_pip_url
    local branch

    repo_url="$(cki_git_clean_url "$1")"
    repo_name=${repo_url%.git/}
    repo_name=${repo_name##*/}
    pip_url="${repo_name/-/_}_pip_url"
    resolved_pip_url="${!pip_url:-}"

    check_interval="1 day"

    cki_echo_yellow "Checking ${repo_name}"
    echo "  Interval: ${check_interval}"
    if ! [[ -d ${repo_name} ]]; then
        if [[ -n ${resolved_pip_url} ]]; then
            cki_echo_red "  not found, cloning override ${resolved_pip_url}"
            branch=${resolved_pip_url##*@}
            repo_url=${resolved_pip_url%@*}
            repo_url="$(cki_git_clean_url "${repo_url}")"
            git clone "${repo_url}" "${repo_name}" --config remote.origin.fetch='+refs/*:refs/remotes/origin/*'
            (cd "${repo_name}" && git switch -c override "origin/${branch}")
        else
            cki_echo_red "  not found, cloning"
            git clone "${repo_url}" "${repo_name}"
        fi
    else
        cd "${repo_name}" || exit 1
        if ! [[ -f .git/FETCH_HEAD ]]; then
            cki_echo_yellow "  FETCH_HEAD not found, pulling"
            git pull
        else
            last_fetch="$(stat -c %Y .git/FETCH_HEAD)"
            threshold="$(date -d -"${check_interval}" +%s)"
            if (( last_fetch < threshold )); then
                cki_echo_yellow "  FETCH_HEAD too old, pulling"
                git pull
            else
                cki_echo_green "  FETCH_HEAD up to date, skipping"
            fi
        fi
        cd "${OLDPWD}" || exit 1
    fi
}

maybe_run_linter() {
    local linter=$1
    local skiped_linters="$2"
    local regex="\b(${linter}|all)\b"
    shift 2
    if [[ "${skiped_linters}" =~ ${regex} ]]; then
        cki_echo_yellow "Skipped ${linter}"
    else
        "run_${linter}" "$@"
    fi
}
